from AOPy import AOPWrapper,weave,getPointcutter
import time

DPFACT = {}


#http://www.daniweb.com/code/snippet216610.html#
def print_timing(func):
    def wrapper(*arg,**kwargs):
        t1 = time.time()
        res = func(*arg,**kwargs)
        t2 = time.time()
        print '%s took %0.3f ms' % (func.func_name, (t2-t1)*1000.0)
        return res
    return wrapper


@weave
def fact(n=0):
    if n==0:
        return 1
    else:
        return n * fact(n=n-1)
    
    
class FactDPAspect(AOPWrapper):
    def __init__(self,signature, numargs, kwargs):
        AOPWrapper.__init__(self, signature, numargs, kwargs)
        self.setBefore(self.before)
        self.setAfter(self.after)
        self.setAround(self.around)
        
    def before(self,*args,**kwargs):
        pass
#        print "before",self.signature
        
    def after(self, retval, exc):
        pass#print "after",self.signature
        
    def around(self,target, method, *args, **kwargs):
        i = kwargs[self.kwargs[0]] #n->value
        if not DPFACT.has_key(i):
            DPFACT[i] = fact(i)
#            print "not in DPFACT"
#        else: print "in DPFact"
        val = DPFACT[i]
        
        return val

@print_timing
def runFact(numtimes=200):
    for i in range(numtimes):
        if i%10==0:
            print "Fact of %2d is %35d" %(i,fact(n=i))
        else:
            fact(n=i)
def main():
    
    runFact()
    factaspect = FactDPAspect("fact","0",["n"])
    getPointcutter().addPointcuter(factaspect)
    runFact()

main()